<template>
    <div class="conter">
        <div :class="float_div_off ? 'float_div' : 'float_div2'">
            <div v-for="(item, index) in getAreaSetList_list" :key="index" style="margin-top:10px"
                @click="selAreaItem(item)" :class="{ 'seled': curAreaId == item.id }">
                <div style="padding:5px;">
                    <div>
                        <div style="font-weight:700;font-size:12px;">区域名称：<span style="font-weight:500;font-size:12px;">{{
                            item.areaName }}</span></div>

                    </div>
                    <div style="margin-top:10px">
                        <div style="font-weight:700;font-size:12px;">中心地址：<span style="font-weight:500;font-size:12px;">{{
                            item.centerAddr }}</span></div>
                    </div>
                    <div style="margin-top:10px">
                        <div style="font-weight:700;font-size:12px;">中心坐标：<span style="font-weight:500;font-size:12px;">{{
                            item.centerLnglat }}</span></div>
                    </div>
                </div>
                <div style="height:2px;width:100%;background:#ddd;"></div>
            </div>

        </div>
        <div @click="float_div_btn" class="float_class">
            <el-icon v-if="float_div_off">
                <DArrowLeft />
            </el-icon>
            <el-icon v-else>
                <DArrowRight />
            </el-icon>


        </div>


        <!-- 地图 -->
        <div class="search-box">
            <el-autocomplete style="width:350px; font-size: 13px;border: 2px solid #30ccc1;color: #30ccc1; outline: none;"
                v-model="searchKey" :clearable="true" :trigger-on-focus="false" :value-key="'address'"
                :fetch-suggestions="queryAddr" :fit-input-width="false" placeholder="请输入地点关键字 例如：成都市 天府广场"
                @select="handleSelAddr">
                <template #default="{ item }">
                    <div class="my-mpoi-list-item">
                        <el-icon class="p-icon">
                            <Location />
                        </el-icon>
                        <div class="p-name">{{ item.address }}</div>
                        <div class="p-addrinfo">
                            {{ item.addrInfo }}
                            <template v-if="item.type">（{{ item.type }}）</template>
                        </div>
                    </div>
                </template>
            </el-autocomplete>

            <el-button-group style="margin-left: 20px;">
                <el-button size="small" type="success" icon="Plus" @click="addArea">新建</el-button>
                <el-button size="small" type="primary" icon="Check" title="保存当前区域" @click="saveCurArea">保存</el-button>
                <el-button size="small" type="warning" icon="Edit" title="编辑当前区域" @click="editCurArea">编辑</el-button>
                <el-button size="small" type="danger" icon="EditPen" title="删除当前区域" @click="delCurArea">删除</el-button>
                <el-button size="small" type="info" icon="Close" title="取消编辑当前区域"
                    @click="cancelEditCurArea">取消编辑</el-button>
            </el-button-group>
        </div>
        <div id="myMap" class="map_class">
        </div>
    </div>
</template>

<script setup>
import { ref, reactive, onMounted } from 'vue'
import AMapLoader from "@amap/amap-jsapi-loader"
import { securityJsCode, key } from '@/utils/common.js'
import { getAreaSetList, adupAreaSet, delAreaSet } from '@/api/customer_list.js'
import { ElMessage, ElLoading, ElMessageBox } from 'element-plus'
onMounted(async () => {
    await getAreaSetList_api()
    window._AMapSecurityConfig = {
        securityJsCode: securityJsCode,
    }
    // 首次加载
    AMapLoader.load({
        key: key,
        version: '2.0',
        plugins: ['AMap.Driving', 'AMap.Geolocation', 'AMap.Scale', 'AMap.AutoComplete', 'AMap.PlaceSearch', 'AMap.Geocoder', 'AMap.PolygonEditor'],
    }).then((AMap) => {
        let clnglat = [104.065861, 30.657401];
        // 初始化-地图对象
        myMap.value = new AMap.Map('myMap', { zoom: 10, center: [104.065861, 30.657401] });

        let timer = null
        clearTimeout(timer)
        timer = setTimeout(() => {
            // 初始化-坐标->地址对象
            geocoder.value = new AMap.Geocoder({ city: '010', radius: 1000 });
            // 初始-中心标记点的信息框
            centerWinInfo.value = new AMap.InfoWindow({
                position: clnglat,
                offset: new AMap.Pixel(0, -30),
                content: '中心点'
            });
            // 初始-中心标记
            centerMarker.value = new AMap.Marker({ position: clnglat, map: myMap.value });

            // 初始化-编辑器对象
            let polyEditor2 = new AMap.PolygonEditor(myMap.value);

            // 为编辑器添加【新增】事件
            console.log(polyEditor2)
            polyEditor2.on('add', function (data) {
                console.log(data, '----111')
                let pg = data.target;
                polyEditor2.addAdsorbPolygons(pg);

                // 设置空，因为新增还没有生成id
                curAreaId.value = null;
                // 保存当前多边形覆盖物对象
                curPolygon.value = pg;

                // 为多边形覆盖物对象添加【单击】事件
                pg.on('click', () => {
                    let pdata = pg.getExtData();
                    if (pdata && pdata.aid) {
                        curAreaId.value = pdata.aid;

                        let areaDat = getAreaByAreaId(curAreaId.value);
                        let point = {
                            address: areaDat.centerAddr,
                            area: areaDat.centerArea,
                            lnglat: areaDat.centerLnglat
                        };
                        setMapCenterMarker(areaDat.areaName, point);
                    } else {
                        saveCurArea();
                    }
                });

                // 为多边形覆盖物对象添加【双击】事件
                pg.on('dblclick', () => {
                    let pdata = pg.getExtData();
                    if (pdata && pdata.aid) curAreaId.value = pdata.aid;

                    polyEditor2.setTarget(pg);
                    polyEditor2.open();
                });
            });
            polyEditor.value = polyEditor2;
            console.log('初始化编辑器对象完成', polyEditor.value);

            // 初始化 - 多边形覆盖物列表(在created中也需要设置)
            if (getAreaSetList_list.value.length > 0) {

                showAreaListInMap()
            }

            clearTimeout(timer)
        }, 100);

    }).catch(err => {
        console.log('高德地图加载失败：', err)
    });

})
const geocoder = ref('')
const myMap = ref('') // 地图
const float_div_off = ref(true) // 左侧浮框弹窗
const centerPoint = ref('')// 中心地点
const centerMarker = ref('')// 中心标记点弹框
const centerWinInfo = ref('') // 中心标记点弹框
const getAreaSetList_list = ref([])// 区域设置列表
const searchKey = ref('') // 搜索地址关键字
const curAreaId = ref('') // 选中的区域id
const curPolygon = ref('') // 当前多边形覆盖物对象
const polyEditor = ref('')    // 编辑器对象
//#region 查询地址



// 初始化在地图上显示区域
const showAreaListInMap = () => {
    // 初始化-多边形覆盖物列表
    if (getAreaSetList_list.value.length > 0) {
        let paths = [];
        getAreaSetList_list.value.forEach(it => {
            let path = [];
            it.boundsPoints.forEach(pit => {
                path.push([parseFloat(pit.lnglat.split(',')[0]), parseFloat(pit.lnglat.split(',')[1])]);
            });

            let cpg = new AMap.Polygon({ path: path });
            // 设置自定义数据对象 区域id
            cpg.setExtData({ aid: it.id });

            // 为多边形覆盖物对象添加【单击】事件
            cpg.on('click', () => {
                // 保存-当前操作多边形覆盖物
                curPolygon.value = cpg;
                let pdata = cpg.getExtData();
                console.log('保存的自定义数据', pdata);
                if (pdata && pdata.aid) {
                    curAreaId.value = pdata.aid;

                    let areaDat = getAreaByAreaId(curAreaId.value);
                    console.log('区域数据', areaDat);
                    let point = {
                        address: areaDat.centerAddr,
                        area: areaDat.centerArea,
                        lnglat: areaDat.centerLnglat
                    };
                    setMapCenterMarker(areaDat.areaName, point);
                }
            });

            // 为多边形覆盖物对象添加【双击】事件
            cpg.on('dblclick', () => {
                if (isNewArea()) {
                    return ElMessage({
                        message: '您有一个区域未保存，清先点击【保存】按钮！',
                        type: 'warning',
                    })
                } else {
                    // 保存-当前操作多边形覆盖物
                    curPolygon.value = cpg;
                    let pdata = cpg.getExtData();
                    if (pdata && pdata.aid) curAreaId.value = pdata.aid;

                    polyEditor.value.setTarget(cpg);
                    polyEditor.value.open();
                }
            });

            paths.push(cpg);
        });
        // 将多边形覆盖物加入到编辑器对象中
        polyEditor.value.addAdsorbPolygons(paths);
        // 将多边形覆盖物加入到地图中显示
        if (paths.length > 0) myMap.value.add(paths);
        // 调整地图视野到中心位置
        myMap.value.setFitView(null, false, null, 11);

        console.log('当前编辑器对象', polyEditor.value);
    }
}

// 是否存在未保存的区域
const isNewArea = () => {
    let pglist = myMap.value.getAllOverlays('polygon');
    return pglist.length > getAreaSetList_list.value.length;
}
// 获取-指定区域id的区域数据对象
const getAreaByAreaId = (id) => {
    let area = getAreaSetList_list.value.find(it => it.id == id);
    return area ? area : null;
}
// 获取-指定多边形覆盖物对象
const getPolygonByAreaId = (id) => {

    let pglist = myMap.value.getAllOverlays('polygon');
    let polygon = pglist.find(it => it.getExtData().aid == id);
    return polygon ? polygon : null;
}

// 设置-地图中心点标记和信息框
const setMapCenterMarker = (areaName, point) => {
    let map = myMap.value
    let cwin = centerWinInfo.value
    let cmarker = centerMarker.value
    console.log('当前标记信息框', cwin, cmarker);

    // 坐标
    let lnglat = [parseFloat(point.lnglat.split(',')[0]), parseFloat(point.lnglat.split(',')[1])];

    // 设置信息框对象（优先设置）
    let winInfo =
        '<div class="cpoint-infowin">' +
        '<p class="ci-area-name">' + areaName + '</p>' +
        '<p class="ci-addr">地址：' + point.address + '</p>' +
        '<p class="ci-area">区域：' + point.area + '</p>' +
        '</div>';
    if (!cwin) {
        cwin = new AMap.InfoWindow({
            position: lnglat,
            offset: new AMap.Pixel(0, -30),
            content: '中心点'
        });
    }
    // 显示信息框
    if (cwin) {
        cwin.setContent(winInfo);
        cwin.open(map, lnglat);
        centerWinInfo.value = cwin;
    }

    // 设置-中心标记
    if (cmarker) {
        cmarker.setPosition(lnglat);
        cmarker.on('click', function () { centerWinInfo.value.open(map); });
        centerMarker.value = cmarker;
        // 显示中心点标记
        centerMarker.value.show();
    }

    // 地图中心点移动到指定点（可以setZoomAndCenter、setFitView方式，均可以达到地图视野在中心的效果，但必须要放到最后）
    map.panTo(lnglat); // 方法一
    // map.setCenter(lnglat); // 方法二
    // map.setFitView([cmarker], false, null, 11); // 方法三
}

/**
  * 查询-地址
  * @param kw 关键字
  * @param cb 返回结果方法
  */
const queryAddr = (kw, cb) => {
    let resList = [];
    AMap.WebService.get('https://restapi.amap.com/v3/place/text',
        { keywords: kw, city: '成都市' },
        function (error, res) {
            // console.log('结果', error, res);
            if (res.info == 'OK') {
                res.pois.forEach(it => {
                    resList.push({
                        id: it.id,
                        // 坐标
                        lnglat: it.location,
                        // 区域 eg：四川省-成都市-武侯区
                        area: `${it.pname}-${it.cityname}-${it.adname}`,
                        // 地址
                        address: `${it.cityname} ${it.name}`,
                        // 地址信息
                        addrInfo: it.address.length == 0 ? '' : it.address,
                        // 地址类型
                        type: it.type ? it.type : '',
                    });
                });
            }
            // 返回结果
            cb(resList);
        }
    );
}
// 选择地址项
const handleSelAddr = (item) => {
    console.log('选择地址', item);

    centerPoint.value = item;

    // 重新设置中心点信息
    setMapCenterMarker('', item);
}

// 显示-区域返回
const selAreaItem = (o) => {

    if (o) {
        curAreaId.value = o.id;
        console.log('当前选中的区域', o);
        // 禁止编辑
        polyEditor.value.close();

        let pg = getPolygonByAreaId(o.id);
        if (pg) {
            curPolygon.value = pg;

            // 选中当前区域，并显示标记及信息框
            let point = {
                address: o.centerAddr,
                area: o.centerArea,
                lnglat: o.centerLnglat
            };
            setMapCenterMarker(o.areaName, point);
        }
    }
}

// 新增-区域
const addArea = () => {

    if (isNewArea()) {
        console.log(111)
        return ElMessage({
            message: '您有一个区域未保存，清先点击【保存】按钮！',
            type: 'warning',
        })
    } else {
        console.log(222)
        polyEditor.value.close();
        polyEditor.value.setTarget();
        polyEditor.value.open();
    }
}

// 保存-当前区域
const saveCurArea = () => {

    if (!polyEditor.value || polyEditor.value.adsorbPolygons.length == 0 || !curPolygon.value) {
        return ElMessage({
            message: '请先选中区域或者新增区域！',
            type: 'warning',
        })
    } else {
        let curArea = null, oldAreaName = null;
        if (curAreaId.value) {
            curArea = getAreaByAreaId(that.curAreaId);
            oldAreaName = curArea.areaName;
            console.log('欲修改的区域', curArea);
        }


        ElMessageBox.prompt(
            '请输入区域名称 如：成都三环内',
            '区域名称设置',
            {
                confirmButtonText: '保存',
                cancelButtonText: '取消',
                type: 'warning',
            }
        )
            .then(({ value }) => {
                // 区域名称
                let areaName = value;

                let isArea = null
                if (curArea) {// 修改
                    isArea = getAreaSetList_list.value.findIndex(it => (areaName != oldAreaName && it.areaName == areaName));
                } else {// 添加
                    isArea = getAreaSetList_list.value.findIndex(it => it.areaName == areaName);
                }
                if (isArea != -1) {
                    return ElMessage({
                        message: '已经存在【' + areaName + '】，请重新输入！',
                        type: 'warning',
                    })

                } else {
                    // 停止编辑
                    polyEditor.value.close();

                    // 获取-多边形的编辑地点坐标
                    let curPolygon = polyEditor.value.getTarget();
                    // console.log('当前多边形', curPolygon);

                    let curPaths = curPolygon.getPath();
                    // console.log('当前多边形编辑点', curPaths);

                    let cMPoint = curPolygon.getBounds().getCenter();
                    console.log('中心点', cMPoint);
                    myMap.value.panTo(cMPoint);

                    let areaPoints = [];
                    if (curPaths.length > 0) {

                        // 将编辑坐标点保存起来
                        let boundsPoints = [];
                        curPaths.forEach(p => { boundsPoints.push({ lnglat: p.lng + ',' + p.lat }); });
                        geocoder.value.getAddress([cMPoint], function (status, result) {
                            if (status === 'complete' && result.info === 'OK') {
                                // result为对应的地理位置详细信息
                                // console.log('坐标解析地址结果', result);
                                let list = result.regeocodes;
                                list.forEach((it, index) => {
                                    let area = it.addressComponent;

                                    let fullArea = area.province + area.city + area.district + area.township;
                                    let fullAddr = it.formattedAddress;
                                    let address = fullAddr.replace(fullArea, '');
                                    // console.log('坐标地址', address);

                                    areaPoints.push({
                                        // 省份-城市-区县
                                        area: area.province + '-' + area.city + '-' + area.district,
                                        // 地址
                                        address: address,
                                        // 坐标
                                        lnglat: cMPoint.lng + ',' + cMPoint.lat
                                    });
                                });
                                // console.log('区域范围坐标点', areaPoints);

                                // 重新设置中心点信息
                                let cpoint = areaPoints[0];
                                console.log('区域范围中心坐标点', cpoint);
                                setMapCenterMarker(areaName, cpoint);

                                let ps = {
                                    areaName: areaName,
                                    boundsLnglat: curPaths.join('='),
                                    caddress: cpoint.address,
                                    clnglat: cpoint.lnglat,
                                    cpoint: `${cpoint.area.split('-')[1]} ${cpoint.address}=${cpoint.lnglat}=${cpoint.area}`,
                                    id: curArea ? curArea.id : '',
                                    ocState: 'OPENED',
                                };
                                console.log('添加、修改区域设置参数', ps);

                                // 此处请求后台保存区域的接口
                                adupAreaSet(ps).then(res => {
                                    if (res.code != 1) {
                                        return ElMessage({
                                            message: res.msg,
                                            type: 'warning',
                                        })
                                    } else {
                                        // 此处使用时间戳作为唯一id（修改不变，添加重新生成id）
                                        let areaId = curArea ? curArea.id : res.areaId;

                                        // 保存当前的区域编辑点
                                        let pdata = {
                                            id: areaId,
                                            areaName: areaName,
                                            centerAddr: cpoint.address,
                                            centerLnglat: cpoint.lnglat,
                                            centerArea: cpoint.area,
                                            boundsPoints: boundsPoints
                                        };
                                        console.log('修改后的区域', pdata);

                                        if (curArea) {
                                            // 更新数据
                                            getAreaSetList_list.value.forEach((it, index) => {
                                                if (it.id == areaId) getAreaSetList_list.value[index] = pdata;
                                            });
                                            console.log('修改后的区域列表', getAreaSetList_list.value);
                                            return ElMessage({
                                                message: '添加区域成功',
                                                type: 'success',
                                            })

                                        } else {
                                            getAreaSetList_list.value.push(pdata);
                                            // 为多边形覆盖物绑定自定义数据
                                            curPolygon.setExtData({ aid: areaId });
                                            return ElMessage({
                                                message: '添加区域成功',
                                                type: 'success',
                                            })

                                        }
                                    }
                                });



                            }
                        });


                    }
                }
            })
            .catch((e) => {
                if (e == 'cancel') {
                    cancelEditCurArea()
                }
            })
    }

}


// 编辑-当前区域
const editCurArea = () => {
    if (isNewArea()) {
        return ElMessage({
            message: '您有一个区域未保存，清先点击【保存】按钮！',
            type: 'warning',
        })
    } else {
        if (!polyEditor.value || polyEditor.value.adsorbPolygons.length == 0 || !curAreaId.value) {
            return ElMessage({
                message: '请先选中区域！',
                type: 'warning',
            })
        } else {
            let pg = getPolygonByAreaId(curAreaId.value);
            if (pg) {
                polyEditor.value.setTarget(pg);
                polyEditor.value.open();
                return ElMessage({
                    message: '开启编辑',
                    type: 'success',
                })
            } else {

                return ElMessage({
                    message: '开启失败',
                    type: 'warning',
                })
            }
        }
    }
}


// 删除-当前区域
const delCurArea = () => {
    if (!polyEditor.value || polyEditor.value.adsorbPolygons.length == 0 || !curPolygon.value) {
        return ElMessage({
            message: '请先选中区域！',
            type: 'warning',
        })
    } else {
        ElMessageBox.confirm(
            '确定删除此区域吗？?',
            {
                confirmButtonText: '确认',
                cancelButtonText: '取消',
                type: 'warning',
                distinguishCancelAndClose: 'true',
            }
        ).then((r) => {
            if (r) {
                console.log(1)
                // 删除区域列表中的数据
                let pdata = curPolygon.value.getExtData();
                if (pdata && pdata.aid) {
                    let index = getAreaSetList_list.value.findIndex(it => it.id == pdata.aid);
                    if (index != -1) {
                        delAreaSet({ ids: [pdata.aid] }).then(res => {
                            if (res.code != 1) {
                                return ElMessage({
                                    message: res.msg,
                                    type: 'warning',
                                })
                            } else {
                                getAreaSetList_list.value.splice(index, 1);
                                // 先要停止编辑，不然编辑点会留在地图上
                                polyEditor.value.close();
                                // 删除编辑器中的多边形覆盖物数据
                                polyEditor.value.removeAdsorbPolygons(curPolygon.value);
                                // 从地图中删除多边形覆盖物、删除标记点、信息框
                                myMap.value.remove([curPolygon.value, centerWinInfo.value]);
                                curPolygon.value.destroy();// 销毁内存
                                curAreaId.value = null;
                                curPolygon.value = null;
                                centerWinInfo.value = null;

                                // 中心点只隐藏，不删除
                                centerMarker.value.hide();

                                // 重新调整地图视野
                                myMap.value.setFitView(null, false, null, 11);
                                return ElMessage({
                                    message: '删除完成',
                                    type: 'success',
                                })
                            }
                        });
                    }
                } else {
                    cancelEditCurArea();
                    return ElMessage({
                        message: '删除区域成功',
                        type: 'success',
                    })
                }
            }
        })
            .catch((e) => {
                if (e == 'cancel') {
                    ElMessage({
                        type: 'warning',
                        message: '取消删除成功',
                    })
                }

            })


    }
}

// 取消编辑当前多边形
const cancelEditCurArea = () => {

    polyEditor.value.close();// 禁止编辑
    if (isNewArea()) {
        polyEditor.value.removeAdsorbPolygons(curPolygon.value);
        myMap.value.remove(curPolygon.value);
        curPolygon.value.destroy();// 销毁内存
        curAreaId.value = null;
        curPolygon.value = null;
    }
}


//#endregion



//#region
const getAreaSetList_find_data = reactive({
    page: {
        pageNum: 1,
        pageSize: 20,
    },
    find: ''
})
const getAreaSetList_api = () => {
    getAreaSetList(getAreaSetList_find_data).then(res => {
        let list = res.data.list
        list.forEach(it => {
            let boundsPoints = [];
            it.boundsLnglat.split('=').forEach(ait => {
                boundsPoints.push({ lnglat: ait });
            });

            getAreaSetList_list.value.push({
                id: it.id,
                areaName: it.areaName,
                centerAddr: it.caddress.split('=')[1],
                centerArea: it.caddress.split('=')[0],
                centerLnglat: it.clnglat,
                boundsPoints: boundsPoints
            });
        });



    })
}
//#endregion


//#region 左边浮框开关

const float_div_btn = () => {
    float_div_off.value = !float_div_off.value
}
//#endregion

</script>

<style scoped lang='scss'>
.seled {
    background: #f3f3f3;
}

.conter {
    position: relative;
    width: 100%;
    display: flex;

    .search-box {
        position: absolute;
        z-index: 5;
        width: 60%;
        left: 30%;
        top: 10px;
        height: 30px;

        .map-search-inp {
            width: 400px;
            font-size: 13px;
            border: 2px solid #30ccc1;
            color: #30ccc1;
            outline: none;

        }

    }
}



.map_class {
    height: 88vh;
    width: 100%;
}

.float_div {
    transition: all 0.3s;
    width: 30%;
    background: white;
    height: 88vh;
    overflow-y: auto;
}

.float_div2 {
    transition: all 0.3s;
    width: 0px;
    background: white;
    height: 88vh;
    overflow-y: auto;
    overflow: hidden;
}

.float_class {
    position: relative;
    left: 0px;
    top: 35vh;
    width: 20px;
    height: 100px;
    background: #15A3FA;
    border-radius: 0px 10px 10px 0px;
    display: flex;
    justify-content: center;
    align-items: center;
    color: #fff;
    font-weight: 700;
}
</style>
<style lang="scss">
.cpoint-infowin {
    max-width: 300px;
}

.ci-area-name {
    margin: 0;
    font-size: 16px;
    color: #2979ff;
    text-align: center;
    font-weight: bold;
}

.ci-addr {
    margin: 0;
    font-size: 13px;
    color: #333;
}

.ci-area {
    margin: 0;
    font-size: 12px;
    color: #666;
}


.my-mpoi-list-item {
    position: relative;
    border-bottom: 1px solid #f3f3f3;
    padding-left: 15px;
    line-height: 25px;

    .p-icon {
        position: absolute;
        top: 4px;
        left: -10px;
        color: #ff9900;
        font-size: 20px;
    }

    .p-name {
        font-size: 15px;
        color: #333;
    }

    .p-addrinfo {
        font-size: 12px;
        color: #666;
    }
}
</style>
